

package com.yungu.swift.order.processor;

import com.alibaba.dubbo.config.annotation.Reference;
import com.yungu.swift.assets.driver.model.vo.DriverVo;
import com.yungu.swift.assets.driver.service.DriverService;
import com.yungu.swift.assets.passenger.model.dto.PassengerCouponDto;
import com.yungu.swift.assets.passenger.model.dto.PassengerDto;
import com.yungu.swift.assets.passenger.model.vo.PassengerVo;
import com.yungu.swift.assets.passenger.service.PassengerCouponService;
import com.yungu.swift.assets.passenger.service.PassengerService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.constants.FinanceConstant;
import com.yungu.swift.constants.OrderConstant;
import com.yungu.swift.constants.PassengerConstant;
import com.yungu.swift.order.model.vo.PayVo;
import com.yungu.swift.order.utils.PayLogBuilder;
import com.yungu.swift.system.finance.model.dto.FinanceOrderDto;
import com.yungu.swift.system.finance.service.FinanceOrderService;
import com.yungu.swift.system.sys.model.dto.SysAccountPassengerDto;
import com.yungu.swift.system.sys.model.dto.SysAccountPlatformDto;
import com.yungu.swift.system.sys.service.SysAccountDriverService;
import com.yungu.swift.system.sys.service.SysAccountPassengerService;
import com.yungu.swift.system.sys.service.SysAccountPlatformService;
import com.yungu.swift.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;


/**
 * Created by cuixiuyin on 2018/5/8.
 * 乘客支付车费处理器
 */
@Component
public class PassengerChargeFareDetailProcessor implements PassengerProcessor {

    private static final Logger logger = LoggerFactory.getLogger(PassengerChargeFareDetailProcessor.class);
    @Reference
    private PassengerService passengerService;
    @Reference
    private DriverService driverService;
    @Reference
    private PassengerCouponService passengerCouponService;
    @Reference
    private SysAccountPlatformService sysAccountPlatformService;
    @Reference
    private SysAccountPassengerService sysAccountPassengerService;
    @Reference
    private FinanceOrderService financeOrderService;
    @Reference
    private SysAccountDriverService sysAccountDriverService;
    @Autowired
    private TransactionTemplate transactionTemplate;


    @Override
    public void process(PayVo payVo) {
        //----------------------------- 乘客支付 ---------------------------------
        //初始化乘客信息
        PassengerVo passengerVo = passengerService.selInfo(payVo.getPassengerVo().getUuid()).getData();
        payVo.setPassengerVo(passengerVo);
        //初始化司机信息
        DriverVo driverVo = payVo.getDriverVo();
        if (driverVo != null) {
            payVo.setDriverVo(driverService.selInfo(driverVo.getUuid()).getData());
        }
        Date date = new Date();
        //平台账户信息
        ResponseData<SysAccountPlatformDto> getPlatformAccount = sysAccountPlatformService.getByAppid(passengerVo.getAppid());
        if (!getPlatformAccount.isSuccess() || getPlatformAccount.getData() == null) {
            logger.warn("获取不到平台账户信息，appid:{}", passengerVo.getAppid());
        }
        SysAccountPlatformDto platformAccount = getPlatformAccount.getData();
        logger.info("优惠券抵扣金额：" + payVo.getActualDeductible() + "，实际支付金额：" + payVo.getActualFare());

        // 存在优惠券抵扣（全抵扣或是部分抵扣）
        if (payVo.getActualDeductible().doubleValue() > 0) {
            couponProcessor(platformAccount, payVo, date);
        }
        // 存在金额支付（余额/微信/支付宝）
        if (payVo.getActualFare().doubleValue() > 0) {
            cashProcessor(platformAccount, payVo, date);
        }
        CompletableFuture.runAsync(() -> {
            //更新乘客信息
            PassengerDto passengerParam = new PassengerDto();
            passengerParam.setUuid(passengerVo.getUuid());
            passengerParam.setToken(passengerVo.getToken());
            //跨城乘客成单量更新移至行程完成后主动调用、其余保留原样
            if (payVo.getOrderDto().getTypeModule() != CommonConstant.BUSINESS_TYPE_POOL) {
                passengerParam.setOrderCount(passengerVo.getOrderCount() == null ? 1 : passengerVo.getOrderCount() + 1);
            }
            passengerService.edit(passengerParam);
        }).whenComplete((t, throwable) -> logger.info("乘客：{}增加订单数：{}成功", passengerVo.getUuid(), payVo.getOrderUuid()));

    }

    private void cashProcessor(SysAccountPlatformDto platformAccount, PayVo payVo, Date date) {
        StringBuffer costDescription = new StringBuffer("乘客通过" + PayLogBuilder.getPayTypeStr(payVo) + "支付行程单" +
                "，支出" + payVo.getActualFare().toString() + "元");
        if (payVo.getActualDeductible().doubleValue() > 0) {
            costDescription.append("，使用优惠券抵扣" + payVo.getActualDeductible().toString() + "元");
        }
        // 余额支付
        if (payVo.getPayType() == OrderConstant.PAY_TYPE_BALANCE) {
            balanceCashProcessor(platformAccount, payVo, date, costDescription);
        }
        // 支付宝支付
        if (payVo.getPayType() == OrderConstant.PAY_TYPE_ALIPAY) {
            aliPayCashProcessor(platformAccount, payVo, date, costDescription);
        }
        // 微信支付
        if (payVo.getPayType() == OrderConstant.PAY_TYPE_TENPAY) {
            weChatPayCashProcessor(platformAccount, payVo, date, costDescription);
        }
    }

    private void weChatPayCashProcessor(SysAccountPlatformDto platformAccount, PayVo payVo, Date date, StringBuffer costDescription) {
        //乘客微信支付累积
        BigDecimal tenpayAccumulate = payVo.getAccountPassengerBean().getTenpayAccumulate() == null ? BigDecimal.ZERO
                : new BigDecimal(payVo.getAccountPassengerBean().getTenpayAccumulate().toString());
        // 增加乘客微信支付流水记录 增加乘客账户微信支付累积金额
        FinanceOrderDto tenpayFinanceOrder = new FinanceOrderDto();
        tenpayFinanceOrder.setUuid(StringUtils.buildUUID());
        tenpayFinanceOrder.setBusinessUuid(payVo.getOrderUuid());
        tenpayFinanceOrder.setOrderUuid(payVo.getOrderUuid());
        tenpayFinanceOrder.setCourse(FinanceConstant.PASSENGER_TEN_PAY);
        tenpayFinanceOrder.setAmount(payVo.getActualFare());
        tenpayFinanceOrder.setFinanceNumber(StringUtils.buildUUID());
        // 乘客 -> 平台
        tenpayFinanceOrder.setFinanceInflow(platformAccount.getUuid());
        tenpayFinanceOrder.setFinanceOutflow(payVo.getPassengerVo().getUuid());
        tenpayFinanceOrder.setDescription("乘客使用微信支付" + payVo.getActualFare() + "元给平台");
        tenpayFinanceOrder.setBusinessUuid(payVo.getFinancePrepayUuid());
        tenpayFinanceOrder.setStartBalance(tenpayAccumulate);
        tenpayFinanceOrder.setHappenTime(date);
        tenpayFinanceOrder.setCreateOn(date);
        tenpayFinanceOrder.setCreateBy(payVo.getUserUuid());
        //增加乘客账户微信支付累积金额
        tenpayAccumulate = tenpayAccumulate.add(payVo.getActualFare());
        tenpayFinanceOrder.setFinalBalance(tenpayAccumulate);
        costDescription.append("乘客微信支付流水记录：乘客使用微信支付车费" + payVo.getActualFare() + "元给平台");

        //修改乘客账户信息
        SysAccountPassengerDto accountPassengerParam = new SysAccountPassengerDto();
        accountPassengerParam.setUuid(payVo.getPassengerVo().getUuid());
        accountPassengerParam.setTenpayAccumulate(tenpayAccumulate);
        accountPassengerParam.setUpdateOn(date);
        accountPassengerParam.setUpdateBy(payVo.getUserUuid());

        transactionTemplate.execute(transactionStatus -> {
            financeOrderService.add(tenpayFinanceOrder);
            sysAccountPassengerService.edit(accountPassengerParam);
            logger.info("订单：{}，微信支付成功，支付信息：{}", payVo.getOrderUuid(), costDescription.toString());
            return Boolean.TRUE;
        });
    }

    private void aliPayCashProcessor(SysAccountPlatformDto platformAccount, PayVo payVo, Date date, StringBuffer costDescription) {
        //乘客支付宝支付累积
        BigDecimal alipayAccumulate = payVo.getAccountPassengerBean().getAlipayAccumulate() == null ? BigDecimal.ZERO
                : new BigDecimal(payVo.getAccountPassengerBean().getAlipayAccumulate().toString());
        // 增加乘客支付宝支付流水记录 增加乘客账户支付宝支付累积金额
        FinanceOrderDto alipayFinanceOrder = new FinanceOrderDto();
        alipayFinanceOrder.setUuid(StringUtils.buildUUID());
        alipayFinanceOrder.setBusinessUuid(payVo.getOrderUuid());
        alipayFinanceOrder.setOrderUuid(payVo.getOrderUuid());
        alipayFinanceOrder.setCourse(FinanceConstant.PASSENGER_ALI_PAY);
        alipayFinanceOrder.setAmount(payVo.getActualFare());
        alipayFinanceOrder.setFinanceNumber(StringUtils.buildUUID());
        // 乘客 ——> 平台
        alipayFinanceOrder.setFinanceInflow(platformAccount.getUuid());
        alipayFinanceOrder.setFinanceOutflow(payVo.getPassengerVo().getUuid());
        alipayFinanceOrder.setDescription("乘客使用支付宝支付" + payVo.getActualFare() + "元给平台");
        alipayFinanceOrder.setBusinessUuid(payVo.getFinancePrepayUuid());
        alipayFinanceOrder.setStartBalance(alipayAccumulate);
        alipayFinanceOrder.setHappenTime(date);
        alipayFinanceOrder.setCreateOn(date);
        alipayFinanceOrder.setCreateBy(payVo.getUserUuid());
        //增加乘客账户支付宝支付累积金额
        alipayAccumulate = alipayAccumulate.add(payVo.getActualFare());
        alipayFinanceOrder.setFinalBalance(alipayAccumulate);

        costDescription.append("乘客支付宝支付流水记录：乘客使用支付宝支付车费" + payVo.getActualFare() + "元");

        //修改乘客账户信息
        SysAccountPassengerDto accountPassengerParam = new SysAccountPassengerDto();
        accountPassengerParam.setUuid(payVo.getPassengerVo().getUuid());
        accountPassengerParam.setAlipayAccumulate(alipayAccumulate);
        accountPassengerParam.setUpdateOn(date);
        accountPassengerParam.setUpdateBy(payVo.getUserUuid());
        transactionTemplate.execute(transactionStatus -> {
            financeOrderService.add(alipayFinanceOrder);
            sysAccountPassengerService.edit(accountPassengerParam);
            logger.info("订单：{}，支付宝支付成功，支付信息：{}", payVo.getOrderUuid(), costDescription.toString());
            return Boolean.TRUE;
        });
    }

    private void balanceCashProcessor(SysAccountPlatformDto platformAccount, PayVo payVo, Date date, StringBuffer costDescription) {
        // 更新账户信息
        SysAccountPassengerDto accountPassengerParam = new SysAccountPassengerDto();
        accountPassengerParam.setUuid(payVo.getPassengerVo().getUuid());
        accountPassengerParam.setUpdateOn(date);
        accountPassengerParam.setUpdateBy(payVo.getUserUuid());

        //实充余额
        BigDecimal rechargeBalance = Optional.ofNullable(payVo.getAccountPassengerBean().getRechargeBalance()).orElse(BigDecimal.ZERO);
        //赠送余额
        BigDecimal presentBalance = Optional.ofNullable(payVo.getAccountPassengerBean().getPresentBalance()).orElse(BigDecimal.ZERO);

        costDescription.append("，账户余额" + rechargeBalance + "元，赠送余额" + presentBalance + "元,");
        //增加乘客余额支付流水 先用充值余额进行支付，不能全部支付需要用到赠送余额支付
        FinanceOrderDto financeOrderDto = new FinanceOrderDto();
        financeOrderDto.setUuid(StringUtils.buildUUID());
        financeOrderDto.setAppid(payVo.getAppid());
        financeOrderDto.setBusinessUuid(payVo.getOrderUuid());
        financeOrderDto.setOrderUuid(payVo.getOrderUuid());
        // 乘客账户 ——> 乘客
        financeOrderDto.setFinanceInflow("");
        financeOrderDto.setFinanceOutflow(payVo.getPassengerVo().getUuid());
        financeOrderDto.setFinanceNumber(StringUtils.buildUUID());
        financeOrderDto.setHappenTime(date);
        financeOrderDto.setCreateOn(date);
        financeOrderDto.setCreateBy(payVo.getUserUuid());

        //由乘客充值余额全部抵扣(大于等于)
        if (rechargeBalance.compareTo(payVo.getActualFare()) != -1) {
            financeOrderDto.setCourse(FinanceConstant.PASSENGER_RECHARGE_BALANCE_PAY);
            financeOrderDto.setAmount(payVo.getActualFare());
            financeOrderDto.setDescription("乘客使用充值余额支付" + payVo.getActualFare() + "元给平台");
            financeOrderDto.setStartBalance(rechargeBalance);
            rechargeBalance = rechargeBalance.subtract(payVo.getActualFare());
            financeOrderDto.setFinalBalance(rechargeBalance);
            financeOrderService.add(financeOrderDto);
            costDescription.append("乘客使用充值余额支付" + payVo.getActualFare() + "元给平台");
            // 修改乘客账户
            accountPassengerParam.setRechargeBalance(rechargeBalance);
            accountPassengerParam.setPresentBalance(presentBalance);
            sysAccountPassengerService.edit(accountPassengerParam);
            logger.info("订单：{}，余额支付修改乘客余额成功，支付信息：{}", payVo.getOrderUuid(), costDescription.toString());
            return;
        }
        // 充值余额 < 订单金额，充值金额 > 0
        if (rechargeBalance.compareTo(payVo.getActualFare()) == -1 && rechargeBalance.compareTo(BigDecimal.ZERO) == 1) {

            BigDecimal amount = payVo.getActualFare().subtract(rechargeBalance);
            //充值余额不为0 且不够完全支付 这边要产生乘客充值余额，乘客赠送余额两条流水记录
            financeOrderDto.setCourse(FinanceConstant.PASSENGER_RECHARGE_BALANCE_PAY);
            financeOrderDto.setAmount(rechargeBalance);
            financeOrderDto.setDescription("乘客使用充值余额支付" + rechargeBalance + "元给平台");
            financeOrderDto.setStartBalance(rechargeBalance);
            rechargeBalance = BigDecimal.ZERO;
            financeOrderDto.setFinalBalance(rechargeBalance);

            costDescription.append("乘客使用充值余额支付，余额" + rechargeBalance + "元全部支付完，");

            //乘客赠送余额流水
            FinanceOrderDto presentBalanceDto = new FinanceOrderDto();
            presentBalanceDto.setUuid(StringUtils.buildUUID());
            presentBalanceDto.setBusinessUuid(payVo.getOrderUuid());
            presentBalanceDto.setOrderUuid(payVo.getOrderUuid());
            presentBalanceDto.setCourse(FinanceConstant.PASSENGER_PRESENT_BALANCE_PAY);
            presentBalanceDto.setAmount(amount);
            presentBalanceDto.setFinanceNumber(StringUtils.buildUUID());
            // 乘客账户-> 乘客
            presentBalanceDto.setFinanceInflow("");
            presentBalanceDto.setFinanceOutflow(payVo.getPassengerVo().getUuid());
            presentBalanceDto.setDescription("乘客使用赠送余额支付" + amount + "元给平台");
            presentBalanceDto.setBusinessUuid(payVo.getFinancePrepayUuid());
            presentBalanceDto.setStartBalance(presentBalance);
            presentBalanceDto.setHappenTime(date);
            presentBalanceDto.setCreateOn(date);
            presentBalanceDto.setCreateBy(payVo.getUserUuid());
            presentBalance = presentBalance.subtract(amount);
            presentBalanceDto.setFinalBalance(presentBalance);

            costDescription.append("乘客使用赠送余额支付" + presentBalance + "元给平台");

            transactionTemplate.execute(transactionStatus -> {
                financeOrderService.add(financeOrderDto);
                financeOrderService.add(presentBalanceDto);
                logger.info("订单：{}，支付信息：{}", payVo.getOrderUuid(), costDescription.toString());
                return Boolean.TRUE;
            });
            // 修改乘客账户
            accountPassengerParam.setRechargeBalance(rechargeBalance);
            accountPassengerParam.setPresentBalance(presentBalance);
            sysAccountPassengerService.edit(accountPassengerParam);
            logger.info("订单：{}，余额支付修改乘客余额成功，支付信息：{}", payVo.getOrderUuid(), costDescription.toString());
            return;
        }

        // 充值金额 = 0， 全部由赠送余额支付
        if (rechargeBalance.compareTo(BigDecimal.ZERO) == 0) {
            //全部由乘客赠送余额支付
            financeOrderDto.setCourse(FinanceConstant.PASSENGER_PRESENT_BALANCE_PAY);
            financeOrderDto.setAmount(payVo.getActualFare());
            financeOrderDto.setDescription("乘客使用赠送余额支付" + payVo.getActualFare() + "元给平台");
            financeOrderDto.setStartBalance(presentBalance);
            presentBalance = presentBalance.subtract(payVo.getActualFare());
            financeOrderDto.setFinalBalance(presentBalance);
            financeOrderService.add(financeOrderDto);
            costDescription.append("乘客使用赠送余额支付" + payVo.getActualFare() + "元给平台");
            // 修改乘客账户
            accountPassengerParam.setRechargeBalance(rechargeBalance);
            accountPassengerParam.setPresentBalance(presentBalance);
            sysAccountPassengerService.edit(accountPassengerParam);
            logger.info("订单：{}，余额支付修改乘客余额成功，支付信息：{}", payVo.getOrderUuid(), costDescription.toString());
            return;
        }
    }

    private void couponProcessor(SysAccountPlatformDto platformAccount, PayVo payVo, Date date) {
        //优惠券累积金额
        BigDecimal couponAccumulate = platformAccount.getCouponAccumulate();
        BigDecimal actualFare = payVo.getActualFare();
        String desription = actualFare.doubleValue() > 0 ? "乘客使用优惠券部分抵扣" + payVo.getActualDeductible() + "元" :
                "乘客使用优惠券全额抵扣" + payVo.getActualDeductible() + "元";
        Integer course = actualFare.doubleValue() > 0 ? FinanceConstant.MARKET_PART_PAY : FinanceConstant.MARKET_FULL_PAY;
        //先增加优惠券抵扣流水，在更新平台账户中的优惠券累积
        FinanceOrderDto financeOrderDto = new FinanceOrderDto();
        financeOrderDto.setUuid(StringUtils.buildUUID());
        financeOrderDto.setAppid(payVo.getAppid());
        financeOrderDto.setBusinessUuid(payVo.getOrderUuid());
        financeOrderDto.setAmount(payVo.getActualDeductible());
        financeOrderDto.setCourse(course);
        financeOrderDto.setFinanceNumber(StringUtils.buildUUID());
        financeOrderDto.setOrderUuid(payVo.getOrderUuid());
        // 平台——>平台账户
        financeOrderDto.setFinanceInflow("");
        financeOrderDto.setFinanceOutflow(platformAccount.getUuid());
        financeOrderDto.setDescription(desription);
        financeOrderDto.setBusinessUuid(payVo.getFinancePrepayUuid());
        financeOrderDto.setStartBalance(couponAccumulate);
        financeOrderDto.setHappenTime(date);
        financeOrderDto.setCreateOn(date);
        financeOrderDto.setCreateBy(payVo.getUserUuid());
        couponAccumulate = couponAccumulate.add(payVo.getActualDeductible());
//        financeOrderDto.setFinalBalance(couponAccumulate.setScale(1, BigDecimal.ROUND_HALF_UP));
        financeOrderDto.setFinalBalance(couponAccumulate.setScale(2, BigDecimal.ROUND_HALF_UP));


        //更新平台账户中的优惠券累积记录
        platformAccount.setUpdateOn(date);
        platformAccount.setCouponAccumulate(couponAccumulate);


        //更新优惠券信息
        PassengerCouponDto passengerCouponParam = new PassengerCouponDto();
        passengerCouponParam.setUuid(payVo.getPassengerCouponUuid());
        passengerCouponParam.setMoney(payVo.getActualDeductible().doubleValue());
        passengerCouponParam.setOrderUuid(payVo.getOrderUuid());
        //已使用
        passengerCouponParam.setStatus(PassengerConstant.COUPON_STATUS_USERED);


        logger.info("乘客支付订单：{}，子处理器——优惠券开始处理", payVo.getOrderUuid());
        transactionTemplate.execute(transactionStatus -> {
            ResponseData<Boolean> addFinanceOrder = financeOrderService.add(financeOrderDto);
            if (addFinanceOrder.isSuccess() && Objects.equals(addFinanceOrder.getData(), Boolean.TRUE)) {
                logger.info("1、优惠券抵扣，插入支付流水成功，orderUuid:{}", payVo.getOrderUuid());
            }
            ResponseData<Boolean> editPlatformAccount = sysAccountPlatformService.edit(platformAccount);
            if (editPlatformAccount.isSuccess() && Objects.equals(editPlatformAccount.getData(), Boolean.TRUE)) {
                logger.info("2、更新平台优惠券累计记录成功，orderUuid:{}", payVo.getOrderUuid());
            }
            ResponseData<Boolean> editPasCoupon = passengerCouponService.edit(passengerCouponParam);
            if (editPasCoupon.isSuccess() && Objects.equals(editPasCoupon.getData(), Boolean.TRUE)) {
                logger.info("3、更新优惠券记录（被使用成功），couponUuid:{}", payVo.getPassengerCouponUuid());
            }
            return Boolean.TRUE;
        });
    }
}
